/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IMAGE_KNIFE_C_KEKE_TASK_WORKER_H
#define IMAGE_KNIFE_C_KEKE_TASK_WORKER_H

#include <thread>
#include "napi/native_api.h"
#include "imageknife_task_internal.h"

namespace ImageKnifePro {

enum class ImageKnifeQOS {
    BACKGROUND = 0,
    UTILITY,
    DEFAULT,
    USER_INITIATED
};

typedef std::function<void(std::shared_ptr<ImageKnifeTaskInternal> task)> AsyncTask;
typedef std::function<void(void *data)> AsyncFunc;

class TaskWorker {
public:
    class TaskHandle {
    public:
        virtual void CancelTask() = 0;
        virtual ~TaskHandle() = default;
    };

    static TaskWorker *GetInstance();
    bool IsMainThread() const;
    void SetEnv(napi_env env);
    napi_env GetEnv() const;

    virtual void SetMaxConcurrency(uint64_t concurrency = 8)
    {
    }

    TaskWorker();
    virtual ~TaskWorker() = default;

    /**
     * @brief 将一个函数下发至子线程执行，根据调用函数所在线程自动使用线程安全函数转发
     * @param execute 任务回调函数，将在子线程中执行
     * @param complete 在任务回调execute执行完成后返回主线程执行
     * @param data 自定义参数，将传递给execute回调以及complete回调
     * @param taskInfo 用于描述任务信息，在发生错误时该信息也会附加至日志上
     * @param qos 设置线程队列优先级，默认优先级为ImageKnifeQOS::DEFAULT
     * @return 创建Task成功返回true,失败返回false
     */
    virtual bool PushTask(AsyncFunc execute, AsyncFunc complete, void *data, std::string taskInfo = "",
                          ImageKnifeQOS qos = ImageKnifeQOS::DEFAULT) = 0;

    /**
     * @brief 将一个函数下发至子线程执行，根据调用函数所在线程自动使用线程安全函数转发
     * @param execute 任务回调函数，将在子线程中执行
     * @param complete 在任务回调execute执行完成后返回主线程执行，可以为nullptr
     * @param task 图片加载任务的描述对象
     * @param qos 设置线程队列优先级，默认优先级为napi_qos_default
     * @return 返回true表示成功从主线程开启了任务，返回false表示开启任务失败
     */
    virtual bool PushTask(AsyncTask execute, AsyncTask complete, std::shared_ptr<ImageKnifeTaskInternal> task,
                          ImageKnifeQOS qos = ImageKnifeQOS::DEFAULT) = 0;

    /**
     * @brief 将一个函数抛回主线程中执行
     * @param func 需要在主线程中执行的函数
     * @param data 自定义参数，将传递给func函数
     */
    virtual void ToMainThread(std::function<void(void*)> func, void* data) = 0;

    /**
     * @brief 将一个函数抛回主线程中，并在给定时间后开始执行
     * @param func 需要在主线程中执行的函数
     * @param data 自定义参数，将传递给func函数
     * @param milliSecond 延迟执行的时间，单位毫秒
     * @return 任务handle,用于取消执行
     */
    virtual std::shared_ptr<TaskHandle> ToMainThreadWithDelay(std::function<void(void*)> func,
                                                              void* data, uint32_t milliSecond)
    {
        // FFRT的版本实现了该函数，但如果后续切换其他线程池实现，对应派生类需实现该函数，否则部分功能不正常
        IMAGE_KNIFE_LOG(LOG_ERROR, "virtual function ToMainThreadWithDelay not implement");
        return nullptr;
    }
protected:
    napi_env env_ = nullptr;
private:
    std::thread::id mainThreadId_;

    virtual void InitNapiEnv()
    {
    }
};
}

#endif //IMAGE_KNIFE_C_KEKE_TASK_WORKER_H
